﻿using BCCommon;
using BCData.TMS.TrainingSite.TrainingSiteBusinessHours;
using BCData.TMS.TrainingSite.TrainingSiteConfig;
using BCDto.Sim.Admin.Admin;
using BCDto.TMS.TrainingSite.TrainingSiteBusinessHours;
using BCDto.TMS.TrainingSite.TrainingSiteConfig;
using BCEntity.Common.EntityNameConst;
using BCEntity.TMS.TrainingSite.TrainingSiteBusinessHours;
using BCEntity.TMS.TrainingSite.TrainingSiteConfig;
using BCService.Common.Area;
using BCService.TMS.Agent.AgentAreaRecord;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace BCService.TMS.TrainingSite.TrainingSiteConfig
{
    public class TrainingSiteConfigService : ITrainingSiteConfigService
    {
        private readonly ITrainingSiteConfigData trainingSiteConfigData;
        private readonly ITrainingSiteBusinessHoursData trainingSiteBusinessHoursData;
        private readonly IRedisService redisService;
        private readonly IDatabaseContext databaseContext;
        private readonly IZoneService zoneService;
        private readonly IAgentAreaRecordService agentAreaRecordService;
        private readonly string key = string.Format("{0}", EntityNameConst.TrainingSiteConfigEntity);

        public TrainingSiteConfigService(ITrainingSiteConfigData trainingSiteConfigData,
            ITrainingSiteBusinessHoursData trainingSiteBusinessHoursData,
            IRedisService redisService,
            IDatabaseContext databaseContext,
            IZoneService zoneService,
            IAgentAreaRecordService agentAreaRecordService)
        {
            this.trainingSiteConfigData = trainingSiteConfigData;
            this.trainingSiteBusinessHoursData = trainingSiteBusinessHoursData;
            this.redisService = redisService;
            this.databaseContext = databaseContext;
            this.zoneService = zoneService;
            this.agentAreaRecordService = agentAreaRecordService;
        }

        public TrainingSiteConfigDto Add(AdminDto admin, TrainingSiteConfigRequestDto dto)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException("非代理商不能添加培训点配置");
            }
            //if (dto.TrainingSiteBusinesses == null || !dto.TrainingSiteBusinesses.Any())
            //{
            //    throw new ArgumentException("培训点营业时间不能为空");
            //}
            //if (dto.TrainingSiteBusinesses.Any(p => ((p.StartHour.HasValue || p.StartMinute.HasValue) && (!p.EndHour.HasValue || !p.EndMinute.HasValue)) ||
            //((!p.StartHour.HasValue || !p.StartMinute.HasValue) && (p.EndHour.HasValue || p.EndMinute.HasValue))))
            //{
            //    throw new ArgumentException("开始时间和结束时间格式不符");
            //}
            //if (dto.TrainingSiteBusinesses.Any(p => p.StartHour.HasValue && p.StartMinute.HasValue && p.EndHour.HasValue && p.EndMinute.HasValue
            //&& (p.EndHour.Value * 100 + p.EndMinute.Value) <= (p.StartHour.Value * 100 + p.StartMinute.Value)))
            //{
            //    throw new ArgumentException("结束时间必须大于开始时间");
            //}
            if (dto.AppointmentAvailable < 0)
            {
                throw new ArgumentException("可预约人数不能小于零");
            }
            var zoneEntity = this.zoneService.GetFromZoneEntity(dto.CountyCode);
            if (zoneEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("区县编码不存在!");
            }
            if (!this.agentAreaRecordService.CheckCountyAuthorize(zoneEntity.countyEntity.CountyCode, admin.AgentRecord.AgentRecordId))
            {
                throw new ArgumentException("此区域授权失败!");
            }
            databaseContext.BeginTransaction();
            var result = this.trainingSiteConfigData.Insert(new TrainingSiteConfigEntity()
            {
                AgentRecordId = admin.AgentRecord.AgentRecordId,
                TrainingSiteName = dto.TrainingSiteName,
                TrainingSiteAddress = dto.TrainingSiteAddress,
                ProvinceCode = zoneEntity.provinceEntity.ProvinceCode,
                ProvinceName = zoneEntity.provinceEntity.ProvinceName,
                CityCode = zoneEntity.cityEntity.CityCode,
                CityName = zoneEntity.cityEntity.CityName,
                CountyCode = zoneEntity.countyEntity.CountyCode,
                CountyName = zoneEntity.countyEntity.CountyName,
                Phone = dto.Phone,
                AppointmentAvailable = dto.AppointmentAvailable,
                CreateTime = DateTime.Now,
                CreateAdminId = admin.AdminId,
                CreateAdminName = admin.FullName,
                UpdateTime = DateTime.Now,
                EditAdminId = admin.AdminId,
                EditAdminName = admin.FullName
            }).GetAwaiter().GetResult();
            //List<TrainingSiteBusinessHoursEntity> businessHoursEntities = new List<TrainingSiteBusinessHoursEntity>();
            //foreach (var item in dto.TrainingSiteBusinesses)
            //{
            //    businessHoursEntities.Add(new TrainingSiteBusinessHoursEntity()
            //    {
            //        TrainingSiteConfigId = result.TrainingSiteConfigId,
            //        AgentRecordId = result.AgentRecordId,
            //        BusinessDay = item.BusinessDay.ToString(),
            //        StartHour = item.StartHour,
            //        StartMinute = item.StartMinute,
            //        EndHour = item.EndHour,
            //        EndMinute = item.EndMinute,
            //        IsBusiness = item.IsBusiness,
            //        CreateTime = DateTime.Now,
            //        UpdateTime = DateTime.Now
            //    });
            //}
            //this.trainingSiteBusinessHoursData.InsertAll(businessHoursEntities).GetAwaiter().GetResult();
            databaseContext.Commit();
            this.redisService.DeleteMultipleKey(key, false);
            return result.As<TrainingSiteConfigDto>();
        }

        public void Delete(AdminDto admin, long trainingSiteConfigId)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException("非代理商不能修改培训点配置");
            }
            var result = this.trainingSiteConfigData.GetEntity(trainingSiteConfigId).Result;
            if (result == null || result.AgentRecordId != admin.AgentRecord.AgentRecordId)
            {
                throw new ArgumentException("培训点信息不存在或此配置不归属您管理");
            }
            databaseContext.BeginTransaction();
            this.trainingSiteConfigData.Delete(trainingSiteConfigId).GetAwaiter().GetResult();
            //this.trainingSiteBusinessHoursData.DeleteByTrainingSiteConfigId(trainingSiteConfigId).GetAwaiter().GetResult();
            databaseContext.Commit();
            string cacheKey = this.redisService.GetKey(key, trainingSiteConfigId);
            this.redisService.DeleteAsync(cacheKey);
        }

        public TrainingSiteConfigDto GetById(long trainingSiteConfigId)
        {
            var result = this.trainingSiteConfigData.GetEntity(trainingSiteConfigId).Result.As<TrainingSiteConfigDto>();
            //if (result != null)
            //{
            //    result.TrainingSiteBusinessHours = this.trainingSiteBusinessHoursData.GetByTrainingSiteConfigId(trainingSiteConfigId).Result.As<List<TrainingSiteBusinessHoursDto>>();
            //}
            return result;
        }

        public IEnumerable<TrainingSiteConfigDto> GetList(long? agentRecordId, string countyCode)
        {
            var cacheKey = this.redisService.GetKey(key, agentRecordId, countyCode);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var data = this.trainingSiteConfigData.GetList(agentRecordId, countyCode).Result;
                return data;
            }, TimeSpan.FromDays(1));
            return result.As<IEnumerable<TrainingSiteConfigDto>>();
        }

        public PageableList<TrainingSiteConfigDto> Query(AdminDto admin, string trainingSiteName, string provinceCode, string cityCode, string countyCode, string phone, int pageIndex, int pageSize)
        {
            string cacheKey = this.redisService.GetKey(key, admin.AgentRecord?.AgentRecordId, trainingSiteName, provinceCode, cityCode, countyCode, phone, pageIndex, pageSize);
            var result = this.redisService.TryGet(cacheKey, () =>
            {
                var (data, dataCount) = this.trainingSiteConfigData.Query(admin.AgentRecord?.AgentRecordId, trainingSiteName, provinceCode, cityCode, countyCode, phone, pageIndex, pageSize).Result;
                var list = data.As<List<TrainingSiteConfigDto>>();
                //if (list.Any())
                //{
                //    var siteBusinessList = this.trainingSiteBusinessHoursData.GetListByConfigIds(list.Select(p => p.TrainingSiteConfigId).ToList()).Result;
                //    foreach (var item in list)
                //    {
                //        item.TrainingSiteBusinessHours = siteBusinessList.Where(p => p.TrainingSiteConfigId == item.TrainingSiteConfigId).As<List<TrainingSiteBusinessHoursDto>>();
                //    }
                //}
                return new PageableList<TrainingSiteConfigDto>()
                {
                    Count = dataCount,
                    Items = list,
                    PageIndex = pageIndex,
                    PageSize = pageSize
                };
            }, TimeSpan.FromDays(1));
            return result;
        }

        public TrainingSiteConfigDto Update(AdminDto admin, long trainingSiteConfigId, TrainingSiteConfigPutDto dto)
        {
            if (admin.AgentRecord == null)
            {
                throw new ArgumentException("非代理商不能修改培训点配置");
            }
            var result = this.trainingSiteConfigData.GetEntity(trainingSiteConfigId).Result;
            if (result == null || result.AgentRecordId != admin.AgentRecord.AgentRecordId)
            {
                throw new ArgumentException("培训点信息不存在或此配置不归属您管理");
            }
            //if (dto.TrainingSiteBusinesses != null && dto.TrainingSiteBusinesses.Any())
            //{
            //    var siteBusiness = this.trainingSiteBusinessHoursData.GetByTrainingSiteConfigId(trainingSiteConfigId).Result;
            //    if (!dto.TrainingSiteBusinesses.All(p => siteBusiness.Any(g => g.TrainingSiteBusinessHoursId == p.TrainingSiteBusinessHoursId)))
            //    {
            //        throw new ArgumentException("培训点营业时间信息有误");
            //    }
            //}
            var zoneEntity = this.zoneService.GetFromZoneEntity(dto.CountyCode);
            if (zoneEntity == null || zoneEntity.countyEntity == null)
            {
                throw new ArgumentException("区县编码不存在!");
            }
            if (!this.agentAreaRecordService.CheckCountyAuthorize(zoneEntity.countyEntity.CountyCode, admin.AgentRecord.AgentRecordId))
            {
                throw new ArgumentException("此区域授权失败!");
            }
            result.TrainingSiteName = dto.TrainingSiteName;
            result.TrainingSiteAddress = dto.TrainingSiteAddress;
            result.ProvinceCode = zoneEntity.provinceEntity.ProvinceCode;
            result.ProvinceName = zoneEntity.provinceEntity.ProvinceName;
            result.CityCode = zoneEntity.cityEntity.CityCode;
            result.CityName = zoneEntity.cityEntity.CityName;
            result.CountyCode = zoneEntity.countyEntity.CountyCode;
            result.CountyName = zoneEntity.countyEntity.CountyName;
            result.Phone = dto.Phone;
            result.AppointmentAvailable = dto.AppointmentAvailable;
            result.UpdateTime = DateTime.Now;
            result.EditAdminId = admin.AdminId;
            result.EditAdminName = admin.FullName;
            //List<TrainingSiteBusinessHoursEntity> businessHoursEntities = new List<TrainingSiteBusinessHoursEntity>();
            //if (dto.TrainingSiteBusinesses != null)
            //{
            //    businessHoursEntities = dto.TrainingSiteBusinesses.As<List<TrainingSiteBusinessHoursEntity>>();
            //    businessHoursEntities.ForEach(p => p.UpdateTime = DateTime.Now);
            //}
            databaseContext.BeginTransaction();
            result = this.trainingSiteConfigData.Update(result).GetAwaiter().GetResult();
            //if (businessHoursEntities.Any())
            //{
            //    this.trainingSiteBusinessHoursData.UpdateAll(businessHoursEntities).GetAwaiter().GetResult();
            //}
            databaseContext.Commit();
            string cacheKey = this.redisService.GetKey(key, trainingSiteConfigId);
            this.redisService.DeleteAsync(cacheKey);
            return result.As<TrainingSiteConfigDto>();
        }
    }
}
